home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / yacas_alg / yacas_morphos / share / yacas / multivar.rep / code.ys < prev   
Encoding:
Text File  |  2002-03-13  |  14.1 KB  |  572 lines

  1.  
  2. /* Sparse multinomial representation
  3.  
  4.    This file implements sparse multivariate polynomial
  5.    representation, along with a few algorithms.
  6.  
  7.    - MakeMultiNomial(expression)
  8.      converts an expression to internal sparse multinomial format.
  9.      NormalForm converts back.
  10.  
  11.  
  12. New proposal for simplify:
  13.  
  14. 1) IsRational a in a+b or a*b etcetera: combine into one rational.
  15. 2) if root expression is rational, call Simplify(a)/Simplify(b)
  16.    or even better: by dividing out the pp of the two (best is gcd).
  17. 3) for normal expression: make multinomial, and return normalized
  18.    content*pp
  19.  */
  20.  
  21. /* We need to include this one because we're extending NormalForm */
  22. /*TODO remove this dependency! */
  23. Use("univar.rep/code.ys");
  24.  
  25.  
  26. MultiSimp(_expr) <--
  27. [
  28.   Local(vars);
  29.   vars:=MultiExpressionList(expr);
  30.   MultiSimp2(MM(expr,vars));
  31. ];
  32.  
  33. 10 # MultiSimp2(_a / _b) <--
  34. [
  35.   Local(c1,c2,gcd,cmn);
  36.  
  37.   gcd:=MultiGcd(a,b);
  38.   c1:=MultiContent(a);
  39.   c2:=MultiContent(b);
  40.  
  41.   gcd:=Gcd(c1[2][1][2],c2[2][1][2]);
  42.   c1[2][1][2] := c1[2][1][2]/gcd;
  43.   c2[2][1][2] := c2[2][1][2]/gcd;
  44.  
  45.   cmn:=Min(c1[2][1][1],c2[2][1][1]);
  46.   c1[2][1][1] := c1[2][1][1] - cmn;
  47.   c2[2][1][1] := c2[2][1][1] - cmn;
  48.  
  49.   (NormalForm(c1)/NormalForm(c2))
  50.     *(NormalForm(MultiPrimitivePart(a))/NormalForm(MultiPrimitivePart(b)));
  51. ];
  52.  
  53. 20 # MultiSimp2(expr_IsMulti) <--
  54. [
  55.   NormalForm(MultiContent(expr))*NormalForm(MultiPrimitivePart(expr));
  56. ];
  57. 30 # MultiSimp2(_expr) <-- expr;
  58.  
  59. MultiExpressionList(_expr) <-- VarList(expr,"IsMultiExpression");
  60. 10 # IsMultiExpression(_x + _y) <-- False;
  61. 10 # IsMultiExpression(_x - _y) <-- False;
  62. 10 # IsMultiExpression(   - _y) <-- False;
  63. 10 # IsMultiExpression(_x * _y) <-- False;
  64. 10 # IsMultiExpression(_x / _y) <-- False;
  65. 10 # IsMultiExpression(_x ^ y_IsInteger) <-- False;
  66. 11 # IsMultiExpression(_x ^ _y)_(IsInteger(Simplify(y))) <-- False;
  67. 10 # IsMultiExpression(x_IsConstant) <-- False;
  68.  
  69. 100 # IsMultiExpression(_x) <-- True;
  70.  
  71.  
  72.  
  73. 10 # IsMulti(MultiNomial(vars_IsList,terms_IsList)) <-- True;
  74. 20 # IsMulti(_anything) <-- False;
  75.  
  76.  
  77.  
  78. RuleBase("MultiNomial",{vars,terms});
  79.  
  80.  
  81. 10 # NormalForm(x_IsMulti/y_IsMulti) <-- NormalForm(x)/NormalForm(y);
  82.  
  83. 20 # NormalForm(MultiNomial(vars_IsList,terms_IsList)) <--
  84. [
  85.   Local(result);
  86.   result:=0;
  87.   ForEach(t,terms)
  88.   [
  89.     result := result + t[2] * Factorize(vars^(t[1]));
  90.   ];
  91.   result;
  92. ];
  93.  
  94. MultiContent(MultiNomial(vars_IsList,terms_IsList))
  95. <--
  96. [
  97.   Local(least,list);
  98.   Set(list,Transpose(terms));
  99.   Set(least, Min(list[1]));
  100.   MultiNomial(vars,{{least,Gcd(list[2])}});
  101. ];
  102.  
  103. MultiPrimitivePart(_multi)
  104. <--
  105. [
  106.   Local(cont);
  107.   cont:=MultiContent(multi);
  108.   cont := MultiNomial(cont[1],{{-cont[2][1][1],1/cont[2][1][2]}});
  109.   MultiNomialMultiply(multi, cont);
  110. ];
  111.  
  112.  
  113. MM(_expr) <--  MM(expr,MultiExpressionList(expr));
  114. MM(_expr,_vars) <--  MakeMultiNomial(expr,vars);
  115.  
  116. MakeMultiNomial(_expr) <-- MakeMultiNomial(ExpandBrackets(expr),MultiExpressionList(expr));
  117.  
  118. LocalSymbols(a,vars)  [
  119.   10 #  MakeMultiNomial(a_IsConstant,vars_IsList) <--
  120.         MultiNomial(vars,{{FillList(0,Length(vars)),a}});
  121. ];
  122.  
  123.  
  124. LocalSymbols(a,vars,pow)  [
  125.   20 #  MultiSingleFactor(_vars,_a,_pow) <--
  126.     [
  127. //Echo({vars,a,pow});
  128.       Local(term);
  129.       term:={FillList(0,Length(vars)),1};
  130.       term[1][Find(vars,a)] := pow;
  131.       MultiNomial(vars,{term});
  132.     ];
  133. ];
  134.  
  135. LocalSymbols(a,vars)  [
  136.   20 #  MakeMultiNomial(_a,vars_IsList)_(Contains(vars,a)) <-- MultiSingleFactor(vars,a,1);
  137. ];
  138.  
  139.  
  140. LocalSymbols(x,y,vars)  [
  141.   30 #  MakeMultiNomial(_x + _y,vars_IsList) <--
  142.         MakeMultiNomial(x,vars) + MakeMultiNomial(y,vars);
  143. ];
  144. LocalSymbols(x,y,vars)  [
  145.   30 #  MakeMultiNomial(_x * _y,vars_IsList) <--
  146.         MakeMultiNomial(x,vars) * MakeMultiNomial(y,vars);
  147. ];
  148.  
  149.  
  150. 10 # MultiRemoveGcd(x_IsMulti/y_IsMulti) <--
  151. [
  152.   Local(gcd);
  153.   Set(gcd,MultiGcd(x,y));
  154.   Set(x,MultiDivide(x,{gcd})[1][1]);
  155.   Set(y,MultiDivide(y,{gcd})[1][1]);
  156.   x/y;
  157. ];
  158. 20 # MultiRemoveGcd(_x) <-- x;
  159.  
  160. LocalSymbols(x,y,vars,gcd,a,a)  [
  161.   30 #  MakeMultiNomial(_x / _y,vars_IsList) <--
  162.         [
  163.           MultiRemoveGcd(MakeMultiNomial(x,vars)/MakeMultiNomial(y,vars));
  164.         ];
  165.   ];
  166.  
  167.  
  168.  
  169. MultiNomial(_vars,_x) + MultiNomial(_vars,_y) <--
  170.        MultiNomialAdd(MultiNomial(vars,x), MultiNomial(vars,y));
  171. MultiNomial(_vars,_x) * MultiNomial(_vars,_y) <--
  172.            MultiNomialMultiply(MultiNomial(vars,x), MultiNomial(vars,y));
  173. MultiNomial(_vars,_x) - MultiNomial(_vars,_y) <--
  174.         MultiNomialAdd(MultiNomial(vars,x), MultiNomialNegate(MultiNomial(vars,y)));
  175.                       - MultiNomial(_vars,_y) <--
  176.         MultiNomialNegate(MultiNomial(vars,y));
  177.  
  178. - MultiNomial(_vars,_x) <--
  179.         MultiNomialNegate(MultiNomial(vars,x));
  180. x_IsMulti + (y_IsMulti/z_IsMulti) <-- ((x*z+y)/z);
  181. (y_IsMulti/z_IsMulti) + x_IsMulti <-- ((x*z+y)/z);
  182.  
  183. (y_IsMulti/z_IsMulti) + (x_IsMulti/w_IsMulti) <-- ((y*w+x*z)/(z*w));
  184. (y_IsMulti/z_IsMulti) - (x_IsMulti/w_IsMulti) <-- ((y*w-x*z)/(z*w));
  185.  
  186. (y_IsMulti/z_IsMulti) * (x_IsMulti/w_IsMulti) <-- ((y*x)/(z*w));
  187. (y_IsMulti/z_IsMulti) / (x_IsMulti/w_IsMulti) <-- ((y*w)/(z*x));
  188.  
  189. x_IsMulti - (y_IsMulti/z_IsMulti) <-- ((x*z-y)/z);
  190. (y_IsMulti/z_IsMulti) - x_IsMulti <-- ((y-x*z)/z);
  191. (a_IsMulti/(c_IsMulti/b_IsMulti))    <-- ((a*b)/c);
  192. ((a_IsMulti/c_IsMulti)/b_IsMulti)    <-- (a/(b*c));
  193. ((a_IsMulti/b_IsMulti) * c_IsMulti)  <-- ((a*c)/b);
  194. (a_IsMulti * (c_IsMulti/b_IsMulti))  <-- ((a*c)/b);
  195. - ((a_IsMulti)/(b_IsMulti))         <-- (-a)/b;
  196.  
  197.  
  198. LocalSymbols(x,vars) [
  199.   30 #  MakeMultiNomial(- _x,vars_IsList) <--
  200.         [
  201.           -MakeMultiNomial(x,vars);
  202.         ];
  203. ];
  204.  
  205. LocalSymbols(x,y,vars) [
  206.   30 #  MakeMultiNomial(_x - _y,vars_IsList) <--
  207.         MakeMultiNomial(x,vars) - MakeMultiNomial(y,vars);
  208. ];
  209.  
  210. LocalSymbols(x,n,vars)  [
  211.   30 #  MakeMultiNomial(_x ^ n_IsInteger,vars_IsList)_(Contains(vars,x)) <--
  212.     MultiSingleFactor(vars,x,n);
  213. ];
  214.  
  215. LocalSymbols(x,n,vars)  [
  216.   40 #  MakeMultiNomial(_x ^ n_IsPositiveInteger,vars_IsList) <--
  217.     [
  218.           Local(mult,result);
  219.           Set(mult,MakeMultiNomial(x,vars));
  220.           Set(result,MakeMultiNomial(1,vars));
  221.       While(n>0)
  222.           [
  223.             If(n&1 != 0, Set(result, MultiNomialMultiply(result,mult)));
  224.             Set(n,n>>1);
  225.             Set(mult,MultiNomialMultiply(mult,mult));
  226.           ];
  227.           result;
  228.         ];
  229.   50 #  MakeMultiNomial(_x ^ (_n),vars_IsList)_(Contains(vars,x)) <--
  230.         [
  231. //Echo({"ENTER!"});
  232.           Set(n,Simplify(n));
  233.           If(IsInteger(n),
  234.             MultiSingleFactor(vars,x,n),
  235.             MultiSingleFactor(vars,x^n,1)
  236.           );
  237.         ];
  238. ];
  239.  
  240. LocalSymbols(x,vars)  [
  241.   100 #  MakeMultiNomial(x_IsFunction,vars_IsList) <--
  242.   [
  243. //Echo({"Adding unknown",x});
  244.          MultiSingleFactor(vars,x,1);
  245.   ];
  246. ];
  247.  
  248. MultiNomialAdd(MultiNomial(_vars,_terms1),MultiNomial(_vars,_terms2)) <--
  249. [
  250.   ForEach(t,terms2) MultiAddTerm(terms1,t);
  251.   MultiNomial(vars,terms1);
  252. ];
  253.  
  254. MultiTermLess({_deg1,_fact1},{_deg2,_fact2}) <--
  255.   [
  256.     Local(deg);
  257.     deg := deg1-deg2;
  258.     While(deg != {} And Head(deg) = 0) [ deg := Tail(deg);];
  259.  
  260.     ((deg = {}) And (fact1-fact2 < 0)) Or
  261.     ((deg != {}) And (deg[1] < 0));
  262.   ];
  263. 10 # MultiAddTerm(_terms,_t)_(Assoc(t[1],terms) = Empty) <--
  264.      [
  265.        Local(i,nr);
  266.        nr:=Length(terms);
  267.        i:=1;
  268.        While (i<=nr And MultiTermLess(t,terms[i])) i++;
  269.        DestructiveInsert(terms,i,t);
  270.        /* DestructiveAppend(terms,t); */
  271.      ];
  272. 20 # MultiAddTerm(_terms,_t) <--
  273.      [
  274.        Local(as);
  275.        as := Assoc(t[1],terms);
  276.        as[2] := as[2] + t[2];
  277.      ];
  278.  
  279.  
  280. MultiNomialMultiply(MultiNomial(_vars,_terms1),MultiNomial(_vars,_terms2)) <--
  281. [
  282.   Local(result,t);
  283.   result := {};
  284.   ForEach(t1,terms1)
  285.     ForEach(t2,terms2)
  286.     [
  287.       t := FlatCopy(t1);
  288.       t[1] := t[1] + t2[1];
  289.       t[2] := t[2] * t2[2];
  290.       MultiAddTerm(result,t);
  291.     ];
  292.   MultiNomial(vars,result);
  293. ];
  294.  
  295. MultiNomialMultiply(
  296.      MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2),
  297.      MultiNomial(_vars,_terms3)/MultiNomial(_vars,_terms4)) <--
  298. [
  299.   MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/
  300.   MultiNomialMultiply(MultiNomial(vars,terms2),MultiNomial(vars,terms4));
  301. ];
  302. MultiNomialMultiply(
  303.      MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2),
  304.      MultiNomial(_vars,_terms3)) <--
  305. [
  306.   MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/
  307.   MultiNomial(vars,terms2);
  308. ];
  309. MultiNomialMultiply(
  310.      MultiNomial(_vars,_terms3),
  311.      MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2)) <--
  312. [
  313.   MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/
  314.   MultiNomial(vars,terms2);
  315. ];
  316.  
  317. 10 # MultiNomialMultiply(_a,_b) <--
  318. [
  319.   Echo({"ERROR!",a,b});
  320.   Echo({"ERROR!",Type(a),Type(b)});
  321. ];
  322.  
  323. MultiNomialNegate(MultiNomial(_vars,_terms)) <--
  324. [
  325.   ForEach(t,terms) [t[2] := -t[2]; ];
  326.   MultiNomial(vars,terms);
  327. ];
  328.  
  329.  
  330.  
  331. 10 # MultiDegree(MultiNomial(_vars,{})) <-- FillList(-Infinity,Length(vars));
  332. 20 # MultiDegree(MultiNomial(_vars,_terms)) <-- Head(Head(terms));
  333.  
  334. 10 # MultiLeadingCoef(MultiNomial(_vars,{})) <-- 0;
  335. 20 # MultiLeadingCoef(MultiNomial(_vars,_terms)) <-- (Head(terms)[2]);
  336.  
  337. 10 # MultiLeadingMono(MultiNomial(_vars,{})) <-- 0;
  338. 20 # MultiLeadingMono(MultiNomial(_vars,_terms)) <-- Factorize(vars^(Head(Head(terms))));
  339.  
  340. 20 # MultiLeadingTerm(_m) <-- MultiLeadingCoef(m) * MultiLeadingMono(m);
  341.  
  342. MultiVars(MultiNomial(_vars,_terms)) <-- vars;
  343.  
  344. 10 # MultiLT(MultiNomial(_vars,{})) <--
  345.      MultiNomial(vars,{{FillList(0,Length(vars)),0}});
  346. 20 # MultiLT(MultiNomial(_vars,_terms)) <-- MultiNomial(vars,{terms[1]});
  347. 10 # MultiLM(MultiNomial(_vars,{})) <-- FillList(0,Length(vars));
  348. 20 # MultiLM(MultiNomial(_vars,_terms)) <-- terms[1][1];
  349. 10 # MultiLC(MultiNomial(_vars,{})) <-- 0;
  350. 20 # MultiLC(MultiNomial(_vars,_terms)) <-- terms[1][2];
  351.  
  352. 10 # MultiZero(MultiNomial(_vars,{})) <-- True;
  353. 20 # MultiZero(MultiNomial(_vars,_terms)) <-- False;
  354.  
  355. DropZeroLC(MultiNomial(_vars,_terms)) <-- MultiNomial(vars,DropZeroLC(terms));
  356. 10 # DropZeroLC({}) <-- {};
  357. 20 # DropZeroLC(terms_IsList) <-- DropZeroLC(Head(terms),Tail(terms));
  358.  
  359. 30 # DropZeroLC({_pows,0},terms_IsList) <-- DropZeroLC(terms);
  360. 40 # DropZeroLC(_pows,terms_IsList) <-- pows:terms;
  361.  
  362. /*
  363.   MultiDivide :
  364.   input
  365.     f - a multivariate polynomial
  366.     g[1 .. n] - a list of polynomials to divide by
  367.   output
  368.     {q[1 .. n],r} such that f = q[1]*g[1] + ... + q[n]*g[n] + r
  369.     
  370.   Basically quotient and remainder after division by a group of
  371.   polynomials.
  372.  */
  373.  
  374.  
  375.  
  376. 20 # MultiDivide(_f,g_IsList) <--
  377. [
  378.   Local(i,v,q,r,nr);
  379.   v:=MultiExpressionList(f+Sum(g));
  380.   f:=MakeMultiNomial(f,v);
  381.   nr := Length(g);
  382.   For(i:=1,i<=nr,i++)
  383.   [
  384.     g[i] := MakeMultiNomial(g[i],v);
  385.   ];
  386.   {q,r}:=MultiDivide(f,g);
  387.   q:=MapSingle("NormalForm",q);
  388.   r:=NormalForm(r);
  389.   {q,r};
  390. ];
  391.  
  392. 10 # MultiDivide(f_IsMulti,g_IsList) <--
  393. [
  394.   Local(i,nr,q,r,p,v,finished);
  395.   Set(nr, Length(g));
  396.   Set(v, MultiVars(f));
  397.   Set(q, FillList(0,nr));
  398.   Set(r, 0);
  399.   Set(p, f);
  400.   Set(finished,MultiZero(p));
  401.   Local(plt,glt);
  402.   While (Not finished)
  403.   [
  404. //Set(g,LocalSymbols(a,b)(Subst(a,b)g));
  405. //Echo({"p = ",p}); //hier
  406. //Echo({""}); //hier
  407.     Set(plt, MultiLT(p));
  408.     For(i:=1,i<=nr,i++)
  409.     [
  410.       Set(glt, MultiLT(g[i]));
  411.       
  412.       if (MultiLM(glt) = MultiLM(plt) Or MultiTermLess({MultiLM(glt),1}, {MultiLM(plt),1}))
  413.       if (Select({{n},n<0},MultiLM(plt)-MultiLM(glt)) = {})
  414.       [
  415.         Local(ff);
  416.         Set(ff, MultiNomial(v,{{MultiLM(plt)-MultiLM(glt),MultiLC(plt)/MultiLC(glt)}}));
  417.         q[i] := q[i] + ff;
  418.         Set(p, p - ff*g[i]);
  419.         Set(i,nr+2);
  420.       ];
  421.     ];
  422.  
  423. //Echo({"p3 = ",p}); //hier
  424. //Echo({"r = ",r});
  425.     If (i = nr+1,
  426.     [
  427.       Set(r, r + LocalSymbols(a,b)(Subst(a,b)plt));
  428.       Set(p,  p - LocalSymbols(a,b)(Subst(a,b)plt));
  429.     ]);
  430. //Echo({"r = ",r});
  431. //Echo({"p4 = ",p}); //hier
  432.     Set(p,DropZeroLC(p));
  433. //    Set(p,DropZeroLC(LocalSymbols(a,b)(Subst(a,b)p)));
  434.  
  435. //Echo({"p5 = ",p}); //hier
  436.     Set(finished,MultiZero(p));
  437.   ];
  438.   {q,r};
  439. ];
  440.  
  441. //TODO optimize this! keeps on converting to and from internal format!
  442.  
  443. 10 # MultiGcd( 0,_g) <-- 1;
  444. 10 # MultiGcd(_f, 0) <-- 1;
  445.  
  446. 20 # MultiGcd(_f,_g) <--
  447. [
  448.   Local(v);
  449.   v:=MultiExpressionList(f+g);  //hier
  450.   NormalForm(MultiGcd(MakeMultiNomial(f,v),MakeMultiNomial(g,v)));
  451. ];
  452.  
  453.  
  454. 5 # MultiGcd(f_IsMulti,g_IsMulti)_(MultiTermLess({MultiLM(f),1},{MultiLM(g),1})) <--
  455. [
  456.   MultiGcd(g,f);
  457. ];
  458.  
  459. 5  # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_(MultiLM(MultiNomial(vars,terms)) = MultiLM(g))
  460.      <--
  461.   MultiNomial(vars,{{FillList(0,Length(vars)),1}});
  462.  
  463. 5  # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_(Select({{n},n<0},MultiLM(MultiNomial(vars,terms))-MultiLM(g)) != {})
  464.      <--
  465.   MultiNomial(vars,{{FillList(0,Length(vars)),1}});
  466.  
  467. 5  # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_(NormalForm(g) = 0)
  468.      <-- MultiNomial(vars,{{FillList(0,Length(vars)),1}});
  469. 10 # MultiGcd(f_IsMulti,g_IsMulti) <--
  470. [
  471.   LocalSymbols(a)
  472.   [
  473.     Set(f,Subst(a,a)f);
  474.     Set(g,Subst(a,a)g);
  475.   ];
  476.   Local(new);
  477.   While(g != 0)
  478.   [
  479.     Set(new, MultiDivide(f,{g})[2]);
  480.     Set(f,g);
  481.     Set(g,new);
  482.   ];
  483.   MultiPrimitivePart(f);
  484. ];
  485.  
  486.  
  487. MultiDivTerm(MultiNomial(_vars,{_term1}),MultiNomial(_vars,{_term2})) <--
  488. [
  489.   MultiNomial(vars,{{term1[1]-term2[1],term1[2]/term2[2]}});
  490. ];
  491. MultiS(_g,_h,MultiNomial(_vars,_terms)) <--
  492. [
  493.   Local(gamma);
  494.   gamma :=Max(MultiDegree(g),MultiDegree(h));
  495.   Local(result);
  496.   result :=
  497.     MultiDivTerm(MultiNomial(vars,{{gamma,1}}),MultiLT(g))*g -
  498.     MultiDivTerm(MultiNomial(vars,{{gamma,1}}),MultiLT(h))*h;
  499.   result;
  500. ];
  501.  
  502. /*
  503.   Groebner : Calculate the Groebner basis of a set of polynomials.
  504.   Nice example of its power is
  505.  
  506. In> TableForm(Groebner({x*(y-1),y*(x-1)}))
  507.  x*y-x
  508.  x*y-y
  509.  y-x
  510.  y^2-y
  511. In> Factor(y^2-y)
  512. Out> y*(y-1);
  513.  
  514. From which you can see that x = y, and x^2 = x so x is 0 or 1.
  515.   
  516. */
  517.  
  518. Groebner(f_IsList) <--
  519. [
  520.   Local(vars,i,j,S,nr,r);
  521.   nr:=Length(f);
  522.   vars:=VarList(f);
  523.   For(i:=1,i<=nr,i++)
  524.   [
  525.     f[i] := MakeMultiNomial(f[i],vars);
  526.   ];
  527.   S:={};
  528.   For(i:=1,i<nr,i++)
  529.   For(j:=i+1,j<=nr,j++)
  530.   [
  531.     r := (MultiDivide(MultiS(f[i],f[j],f[i]),f)[2]);
  532.     If(NormalForm(r) != 0, S:= r:S);
  533.     f:=Concat(f,S);
  534.     S:={};
  535.     nr:=Length(f);
  536.   ];
  537.   MapSingle("NormalForm",Concat(f));
  538. ];
  539.  
  540.  
  541. /*
  542. tst:= (-2*m^3*y)/M^2-(m^2*y)/M+m*y+1/(1/(2*y*m+(-6*y*m^2)/M+(4*m^3*y)/M^2)+1/((-6*m^2*y)/M+(4*m^3*y)/M^2+2*y*m));
  543.  
  544. try(f):=
  545. [
  546.   Echo({"In> ",f});
  547.   Local(ms);
  548.   ms:=MultiSimp(f);
  549.   Echo({"Out> ",ms});
  550. ];
  551. //try(D(x,4)Exp((-x^2)/2));
  552.  
  553. //try(1/(1+1/x));
  554. //try(1/(1+1/(1+1/x)));
  555.  
  556. tryfull():=
  557. [
  558.   exp:=1/x;
  559.   While(True)
  560.   [
  561.     try(exp);
  562.     exp:=1/(1+exp);
  563.   ];
  564. ];
  565.  
  566. //try(1/(1+1/(1+1/(1+1/x))));
  567. //try(tst);
  568.  
  569. //(-2 m^3 y)/M^2-(m^2 y)/M+m y+1/(1/(2 y m+(-6 y m^2)/M+(4 m^3 y)/M^2)+1/((-6 m^2 y)/M+(4 m^3 y)/M^2+2 y m))
  570.  
  571. */
  572.